package com.example.everying.framework.pay.service;

import com.example.everying.config.WeChatConfig;
import com.example.everying.model.dto.pay.TransferToUserRequest;
import com.example.everying.model.dto.pay.TransferToUserResponse;
import com.example.everying.utils.CampusException;
import com.example.everying.utils.WXPayUtility;
import com.example.everying.utils.WeChatUtil;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.transferbatch.TransferBatchService;
import com.wechat.pay.java.service.transferbatch.model.*;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class WechatTransferServiceImpl implements WechatTransferService {
    @Autowired
    private TransferBatchService transferBatchService;
    @Autowired
    private WeChatConfig weChatConfig;
    //    private final String mchid;
//    private final String certificateSerialNo;
//    private  final PrivateKey privateKey = WXPayUtility.loadPrivateKeyFromPath(weChatConfig.privateKeyPath);
    //    private final String wechatPayPublicKeyId;
//    private final PublicKey wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(weChatConfig.publicKeyPath);

    private static final String HOST = "https://api.mch.weixin.qq.com";
    private static final String METHOD = "POST";
    private static final String PATH = "/v3/fund-app/mch-transfer/transfer-bills";
    private static final String QUERY_METHOD = "GET";
    private static final String QUERY_PATH = "/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}";

//    WechatTransferServiceImpl client = new WechatTransferServiceImpl(weChatConfig.getMerchantId(),weChatConfig.merchantSerialNumber,weChatConfig.privateKeyPath,weChatConfig.publicKeyId,weChatConfig.publicKeyPath);
//    public  WechatTransferServiceImpl(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) {
//        this.mchid = mchid;
//        this.certificateSerialNo = certificateSerialNo;
//        this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath);
//        this.wechatPayPublicKeyId = wechatPayPublicKeyId;
//        this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
//    }
    @Override
    public TransferToUserResponse transfer(TransferToUserRequest request) {
        try {
            TransferToUserResponse response = run(request);
            if (response != null){
                response.setAppId(weChatConfig.getAppId());
                response.setMchId(weChatConfig.getMerchantId());
            }
            return response;
        } catch (WXPayUtility.ApiException e) {
            // 获取具体的错误消息
            String errorMessage = e.getMessage();
            log.error(" 微信支付失败: 状态码={}, 错误信息={}", e.statusCode,  errorMessage);

            // 根据不同的错误码处理业务逻辑
            if (e.statusCode  == 400 && errorMessage.contains(" 实名不一致")) {
                throw new CampusException("收款人姓名与微信实名认证不符，请核对后重试",201);
            } else {
                throw new CampusException("网络故障，请稍后重试", 201);
            }
        }
    }

    public TransferToUserResponse run(TransferToUserRequest request) {
        String uri = PATH;
        request.setAppid(weChatConfig.getAppId());  // 微信分配的appid
        request.setNotifyUrl(weChatConfig.getTransferNotifyUrl());
        log.info("转账回调地址：{}", weChatConfig.getTransferNotifyUrl());
        request.setTransferSceneId("1005"); // 佣金报酬
        // 处理userName 收款方真实姓名。需要加密传入，支持标准RSA算法和国密算法，公钥由微信侧提供
        request.setUserName(encrypt(request.getUserName()));
        String reqBody = WXPayUtility.toJson(request);
        log.info("提现请求微信 reqBody : {}", reqBody);

        Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
        reqBuilder.addHeader("Accept", "application/json");
        reqBuilder.addHeader("Wechatpay-Serial", weChatConfig.publicKeyId);
        reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(weChatConfig.getMerchantId(), weChatConfig.merchantSerialNumber, WXPayUtility.loadPrivateKeyFromPath(weChatConfig.privateKeyPath), METHOD, uri, reqBody));
        reqBuilder.addHeader("Content-Type", "application/json");
        MediaType mediaType = MediaType.get("application/json; charset=utf-8");
        RequestBody requestBody = RequestBody.create(reqBody, mediaType);
        reqBuilder.method(METHOD, requestBody);
        Request httpRequest = reqBuilder.build();

        // 发送HTTP请求
        OkHttpClient client = new OkHttpClient.Builder().build();
        log.info("提现请求微信: {}", httpRequest);
        try (Response httpResponse = client.newCall(httpRequest).execute()) {
            String respBody = WXPayUtility.extractBody(httpResponse);
            if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
                // 2XX 成功，验证应答签名
                WXPayUtility.validateResponse(weChatConfig.publicKeyId, WXPayUtility.loadPublicKeyFromPath(weChatConfig.publicKeyPath),
                        httpResponse.headers(), respBody);

                // 从HTTP应答报文构建返回数据
                return WXPayUtility.fromJson(respBody, TransferToUserResponse.class);
            } else {
                throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
            }
        } catch (IOException e) {
            throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
        }
    }

    public String encrypt(String plainText) {
        return WXPayUtility.encrypt(WXPayUtility.loadPublicKeyFromPath(weChatConfig.publicKeyPath), plainText);
    }

    /**
     * 通过商户单号查询转账单
     *
     * @param outBillNo 商户单号
     * @return 转账单详情
     */
    @Override
    public TransferToUserResponse queryTransferBillByOutNo(String outBillNo) {
        try {
            TransferToUserResponse response = runQuery(outBillNo);
            if (response != null) {
                response.setAppId(weChatConfig.getAppId());
                response.setMchId(weChatConfig.getMerchantId());
            }
            return response;
        } catch (WXPayUtility.ApiException e) {
            String errorMessage = e.getMessage();
            log.error(" 查询微信转账单失败: 状态码={}, 错误信息={}", e.statusCode, errorMessage);
            throw new CampusException("查询转账单失败，请稍后重试", 201);
        }
    }

    public TransferToUserResponse runQuery(String outBillNo) {
        String uri = QUERY_PATH.replace("{out_bill_no}", WXPayUtility.urlEncode(outBillNo));
        
        Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
        reqBuilder.addHeader("Accept", "application/json");
        reqBuilder.addHeader("Wechatpay-Serial", weChatConfig.publicKeyId);
        reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(
                weChatConfig.getMerchantId(), 
                weChatConfig.merchantSerialNumber, 
                WXPayUtility.loadPrivateKeyFromPath(weChatConfig.privateKeyPath), 
                QUERY_METHOD, 
                uri, 
                null));
        
        reqBuilder.method(QUERY_METHOD, null);
        Request httpRequest = reqBuilder.build();

        // 发送HTTP请求
        OkHttpClient client = new OkHttpClient.Builder().build();
        log.info("查询微信转账单: {}", httpRequest);
        try (Response httpResponse = client.newCall(httpRequest).execute()) {
            String respBody = WXPayUtility.extractBody(httpResponse);
            if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
                // 2XX 成功，验证应答签名
                WXPayUtility.validateResponse(
                        weChatConfig.publicKeyId, 
                        WXPayUtility.loadPublicKeyFromPath(weChatConfig.publicKeyPath),
                        httpResponse.headers(), 
                        respBody);

                // 从HTTP应答报文构建返回数据
                return WXPayUtility.fromJson(respBody, TransferToUserResponse.class);
            } else {
                throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
            }
        } catch (IOException e) {
            throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
        }
    }

    /**
     * 发起商家转账
     *
     * @param outBatchNo      商户批次单号
     * @param batchRemark     批次备注
     * @param transferDetails 转账明细列表
     * @return 转账响应
     */
    @Override
    public InitiateBatchTransferResponse initiateTransfer(
            String outBatchNo,
            String batchRemark,
            List<TransferDetailInput> transferDetails) {

        // 计算总金额和总笔数
        int totalAmount = Math.toIntExact(transferDetails.stream().mapToLong(TransferDetailInput::getTransferAmount).sum());
        int totalNum = transferDetails.size();

        // 构建请求
        InitiateBatchTransferRequest request = new InitiateBatchTransferRequest();
        request.setAppid(weChatConfig.getAppId());  // 微信分配的appid
        request.setOutBatchNo(outBatchNo);
        request.setBatchName(batchRemark);
        request.setBatchRemark(batchRemark);
        request.setTotalAmount((long) totalAmount);
        request.setTotalNum(totalNum);
//        request.setNotifyUrl(weChatConfig.getPayNotifyUrl());
        request.setTransferSceneId("1005"); // 佣金报酬

        // 添加转账明细
//        List<TransferDetailInput> detail = new ArrayList<>();
//        for (TransferDetailInput detail : transferDetails) {
//
//        }
        request.setTransferDetailList(transferDetails);
        InitiateBatchTransferResponse response = new InitiateBatchTransferResponse();
        // 调用接口
        try {
            // 调用转账接口
            response = transferBatchService.initiateBatchTransfer(request);
            log.info(" 转账批次创建成功，响应参数: {}", response);


        } catch (HttpException e) {
            log.error("HTTP 请求失败 - 请求方法: {}, URL: {}",
                    e.getHttpRequest().getHttpMethod(),
                    e.getHttpRequest().getUrl(),
                    e);

        } catch (ValidationException e) {
            log.error(" 微信支付返回签名验证失败", e);

        } catch (ServiceException e) {
            log.error(" 微信支付返回业务错误 - 错误码: {}, 错误信息: {}",
                    e.getErrorCode(),
                    e.getErrorMessage(),
                    e);

        } catch (MalformedMessageException e) {
            log.error(" 无法解析微信支付响应", e);

        } catch (Exception e) {
            log.error(" 处理微信支付转账时发生未知异常", e);
        }
        return response;
    }

    /**
     * 通过商户批次单号查询批次单
     *
     * @param outBatchNo      商户批次单号
     * @param needQueryDetail 是否需要查询明细
     * @param detailStatus    明细状态(可选)
     * @return 批次单详情
     */
    @Override
    public TransferBatchEntity queryBatchByOutBatchNo(
            String outBatchNo,
            boolean needQueryDetail,
            String detailStatus) {

        GetTransferBatchByOutNoRequest request = new GetTransferBatchByOutNoRequest();
        request.setOutBatchNo(outBatchNo);
        request.setNeedQueryDetail(needQueryDetail);

        if (detailStatus != null) {
            request.setDetailStatus(detailStatus);
        }

        return transferBatchService.getTransferBatchByOutNo(request);
    }

    /**
     * 通过微信明细单号查询明细单
     *
     * @param batchId  微信批次单号
     * @param detailId 微信明细单号
     * @return 明细单详情
     */
    @Override
    public TransferDetailEntity queryDetailByDetailId(String batchId, String detailId) {
        GetTransferDetailByNoRequest request = new GetTransferDetailByNoRequest();
        request.setBatchId(batchId);
        request.setDetailId(detailId);

        return transferBatchService.getTransferDetailByNo(request);
    }

    /**
     * 通过商户明细单号查询明细单
     *
     * @param outBatchNo  商户批次单号
     * @param outDetailNo 商户明细单号
     * @return 明细单详情
     */
    @Override
    public TransferDetailEntity queryDetailByOutDetailNo(String outBatchNo, String outDetailNo) {
        GetTransferDetailByOutNoRequest request = new GetTransferDetailByOutNoRequest();
        request.setOutBatchNo(outBatchNo);
        request.setOutDetailNo(outDetailNo);

        return transferBatchService.getTransferDetailByOutNo(request);
    }

    /**
     * 下单支付回调
     *
     * @param request HttpServletRequest
     * @return 通知结果
     */
    public Map transferCallback(HttpServletRequest request) throws IOException {
        log.info("微信支付回调开始解析数据");

        RequestParam requestParam = WeChatUtil.handleNodifyRequestParam(request);

        //构建通知解析器com.wechat.pay.java.core.notification.NotificationParser
        NotificationParser parser = weChatConfig.notificationParser();
        //验签、解密并转换成 com.wechat.pay.java.service.payments.model.Transaction
        return parser.parse(requestParam, Map.class);//获取通知结果
    }
//    /**
//     * 下单支付回调
//     *
//     * @param request HttpServletRequest
//     */
//    @Override
//    public void transferCallback(HttpServletRequest request) throws IOException {
//
//        // 获取body参数
//        String bodyStr = ServletUtil.getBody(request);
//        log.info("商家转账-微信回调：{}", JSON.toJSONString(bodyStr));
//        try {
//            // 校验平台证书的序列号
//            String serial = request.getHeader("Wechatpay-Serial");
//            if (!this.getX509Certificate().getSerialNumber().toString(16).toUpperCase().equals(serial)) {
//                this.buildFailResponse(response, "平台证书序列号错误");
//                return;
//            }
//            // 只允许5分钟的时间偏差
//            Long timestamp = Long.valueOf(request.getHeader("Wechatpay-Timestamp"));
//            if (5 * 60 < System.currentTimeMillis() - timestamp * 1000) {
//                this.buildFailResponse(response, "时间戳不正确");
//                return;
//            }
//            // 验签
//            boolean flag = this.checkSign(request, bodyStr);
//            if (!flag) {
//                this.buildFailResponse(response, "验签失败");
//                return;
//            }
//            // 解密body参数
//            JSONObject body = this.getBodyParams(bodyStr);
//            log.info("商家转账-微信回调-解密得到body：{}", JSON.toJSONString(body));
//            /**
//             * TODO 你自己的业务逻辑
//             */
//            // 返回处理成功
//            response.setStatus(HttpStatus.OK.value());
//            return;
//        } catch (Exception e) {
//            log.error("商家转账-回调异常", e);
//        }
//        return null;
//    }
//
//    /**
//     * 返回错误信息
//     */
//    private void buildFailResponse(HttpServletResponse response, String msg) throws IOException {
//        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
//        JSONObject resJson = new JSONObject().fluentPut("code", "SUCCESS").fluentPut("message", msg);
//        response.getWriter().write(resJson.toJSONString());
//    }
//
//    /**
//     * 签名验证
//     */
//    private boolean checkSign(HttpServletRequest request, String bodyStr) {
//        // 时间戳
//        String Timestamp = request.getHeader("Wechatpay-Timestamp");
//        // 随机字符串
//        String Nonce = request.getHeader("Wechatpay-Nonce");
//        // 签名字符串
//        String Signature = request.getHeader("Wechatpay-Signature");
//        try {
//            // 拼接字符串
//            String srcData = Timestamp + "\n" + Nonce + "\n" + bodyStr + "\n";
//            // 验证签名
//            return verify(srcData, getX509Certificate(), Signature);
//        } catch (Exception e) {
//            log.error("商家转账-转账回调：验签异常", e);
//        }
//        return false;
//    }
//
//    /**
//     * 验证签名
//     *
//     * @param srcData     拼接字符串
//     * @param certificate 验签工具
//     * @param Sign        微信签名串
//     */
//    private boolean verify(String srcData, X509Certificate certificate, String Sign) throws Exception {
//        Signature sha256withRSA = Signature.getInstance("SHA256withRSA");
//        sha256withRSA.initVerify(certificate.getPublicKey());
//        sha256withRSA.update(srcData.getBytes());
//        return sha256withRSA.verify(Base64Utils.decodeFromString(Sign));
//    }
//
//    /**
//     * 获取 X509Certificate
//     */
//    private X509Certificate getX509Certificate() {
//        ClassLoader classLoader = this.getClass().getClassLoader();
//        try (InputStream in = classLoader.getResourceAsStream("v3/platform_cert.pem")) {
//            if (in == null) {
//                throw new IOException("Resource not found: v3/platform_cert.pem");
//            }
//            CertificateFactory cf = CertificateFactory.getInstance("X.509");
//            return (X509Certificate) cf.generateCertificate(in);
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
//    }
//
//    /**
//     * 解密body参数
//     */
//    private JSONObject getBodyParams(String bodyStr) {
//        JSONObject body = JSONObject.parseObject(bodyStr);
//        JSONObject resourceJson = JSONObject.parseObject(body.getString("resource"));
//        WXTransferAesUtil WXTransferAesUtil = new WXTransferAesUtil(weChatConfig.privateKeyPath.getBytes());
//        try {
//            String res = WXTransferAesUtil.decryptToString(resourceJson.getString("associated_data").getBytes(), resourceJson.getString("nonce").getBytes(), resourceJson.getString("ciphertext"));
//            return JSONObject.parseObject(res);
//        } catch (Exception e) {
//            log.error("商家转账-转账回调：body解密失败", e);
//        }
//        return null;
//    }
}
